local u = require('util')
local M = {}

function M.setup()
  -- 基础快捷键
  vim.g.mapleader = " "

  -- filetree
  u.nnoremap('<c-n>', ':NvimTreeToggle<cr>')
  u.nnoremap('<leader>n', ':NvimTreeFindFile<cr>')

  -- fuzzy
  u.nnoremap('<leader>ff',':Telescope find_files<cr>')
  u.nnoremap('<leader>fg',':Telescope live_grep<cr>')
  u.nnoremap('<leader>fb',':Telescope buffers<cr>')
  u.nnoremap('<leader>fh',':Telescope help_tags<cr>')

  --saga terminal
  u.nnoremap('<c-x>t', ':Lspsaga open_floaterm<cr>')
  u.tnoremap('<c-x>t', '<c-\\><c-n>:Lspsaga close_floaterm<cr>')

  -- rest http client
  u.nnoremap('<c-x>rc', ':lua require("rest-nvim").run()<cr>')
  u.nnoremap('<c-x>rp', ':lua require("rest-nvim").run(true)<cr>')
  u.nnoremap('<c-x>rr', ':lua require("rest-nvim").last()<cr>')
end

-- FileTree
function M.filetree_mapping(tree_cb)
  vim.g.nvim_tree_bindings = {
      { key = {"<CR>", "o", "<2-LeftMouse>"}, cb = tree_cb("edit") },
      { key = {"<2-RightMouse>", "<C-]>"},    cb = tree_cb("cd") },
      { key = "v",                        cb = tree_cb("vsplit") },
      { key = "x",                        cb = tree_cb("split") },
      { key = "t",                        cb = tree_cb("tabnew") },
      { key = "<",                            cb = tree_cb("prev_sibling") },
      { key = ">",                            cb = tree_cb("next_sibling") },
      { key = "P",                            cb = tree_cb("parent_node") },
      { key = "<BS>",                         cb = tree_cb("close_node") },
      { key = "<S-CR>",                       cb = tree_cb("close_node") },
      { key = "<Tab>",                        cb = tree_cb("preview") },
      { key = "K",                            cb = tree_cb("first_sibling") },
      { key = "J",                            cb = tree_cb("last_sibling") },
      { key = "I",                            cb = tree_cb("toggle_ignored") },
      { key = "H",                            cb = tree_cb("toggle_dotfiles") },
      { key = "R",                            cb = tree_cb("refresh") },
      { key = "a",                            cb = tree_cb("create") },
      { key = "d",                            cb = tree_cb("remove") },
      { key = "r",                            cb = tree_cb("rename") },
      { key = "<C-r>",                        cb = tree_cb("full_rename") },
      { key = "x",                            cb = tree_cb("cut") },
      { key = "c",                            cb = tree_cb("copy") },
      { key = "p",                            cb = tree_cb("paste") },
      { key = "y",                            cb = tree_cb("copy_name") },
      { key = "Y",                            cb = tree_cb("copy_path") },
      { key = "gy",                           cb = tree_cb("copy_absolute_path") },
      { key = "[c",                           cb = tree_cb("prev_git_item") },
      { key = "]c",                           cb = tree_cb("next_git_item") },
      { key = "-",                            cb = tree_cb("dir_up") },
      { key = "s",                            cb = tree_cb("system_open") },
      { key = "q",                            cb = tree_cb("close") },
      { key = "g?",                           cb = tree_cb("toggle_help") },
    }
end


-- 补全
function M.cmp_mapping(cmp)
  return {
        ['<c-p>'] = cmp.mapping.select_prev_item(),
        ['<c-n>'] = cmp.mapping.select_next_item(),
        ['<c-d>'] = cmp.mapping.scroll_docs(-4),
        ['<c-f>'] = cmp.mapping.scroll_docs(4),
        ['<c-space>'] = cmp.mapping.complete(),
        ['<c-e>'] = cmp.mapping.close(),
        ['<cr>'] = cmp.mapping.confirm({
          behavior = cmp.ConfirmBehavior.Replace,
          select = true,
        }),
        ['<tab>'] = cmp.mapping.confirm({
          behavior = cmp.ConfirmBehavior.Insert,
          select = true,
        })
  }
end

-- LSP
function M.lsp_mapping_on_attach(_, bufnr)
  u.opt.b('omnifunc', 'v:lua.vim.lsp.omnifunc')
  -- 跳转到定义
	u.nnoremap_buf(bufnr, 'gd', '<cmd>lua vim.lsp.buf.definition()<CR>')
  -- 跳转到 declarition
	u.nnoremap_buf(bufnr, 'gD', '<cmd>lua vim.lsp.buf.declaration()<CR>')
  -- 跳转到实现
	u.nnoremap_buf(bufnr, 'gi', '<cmd>lua vim.lsp.buf.implementation()<CR>')
  -- 跳转到引用
	u.nnoremap_buf(bufnr, 'gr', '<cmd>lua vim.lsp.buf.references()<CR>')
  -- 重命名
	u.nnoremap_buf(bufnr, '<leader>R', ':Lspsaga rename<cr>')
  -- hover doc
	u.nnoremap_buf(bufnr, 'M', ':Lspsaga hover_doc<cr>')
  -- 方法签名
	u.nnoremap_buf(bufnr, '<c-m>', ':Lspsaga signature_help<cr>')
  -- HINT: 会导致 i 模式下 enter 键进入 n 模式, 暂时不明白原因
	-- u.inoremap_buf(bufnr, '<c-m>', '<c-\\><c-n>:Lspsaga signature_help<cr>')
  -- 预览定义和引用
  u.nnoremap_buf(bufnr, '<leader>r', ':Lspsaga lsp_finder<cr>')
	--u.nnoremap_buf(bufnr, '<leader>D', '<cmd>lua vim.lsp.buf.type_definition()<CR>')
  -- 预览定义 - sega
	u.nnoremap_buf(bufnr, '<leader>d', ':Lspsaga preview_definition<cr>')

  -- 诊断
	u.nnoremap_buf(bufnr, '<leader>e', ':Lspsaga show_line_diagnostics<cr>')
	u.nnoremap_buf(bufnr, 'g]e', ':Lspsaga diagnostic_jump_next<cr>')
	u.nnoremap_buf(bufnr, 'g[e', ':Lspsaga diagnostic_jump_priv<cr>')

  -- 格式化
	u.nnoremap_buf(bufnr, '<leader>f', '<cmd>lua vim.lsp.buf.formatting()<CR>')

  -- code action
	u.nnoremap_buf(bufnr, '<leader>ca', ':Lspsaga code_action<cr>')


  -- trouble
  u.nnoremap_buf(bufnr, '<leader>xx', ':TroubleToggle<cr>')
  u.nnoremap_buf(bufnr, '<leader>xw', ':TroubleToggle lsp_workspace_diagnostics<cr>')
  u.nnoremap_buf(bufnr, '<leader>xd', ':TroubleToggle lsp_document_diagnostics<cr>')
  u.nnoremap_buf(bufnr, '<leader>xq', ':TroubleToggle quickfix<cr>')
  u.nnoremap_buf(bufnr, '<leader>xl', ':TroubleToggle loclist<cr>')

	--u.nnoremap_buf(bufnr, '<space>q', '<cmd>lua vim.lsp.diagnostic.set_loclist()<CR>')
	--u.nnoremap_buf(bufnr, '<space>wa', '<cmd>lua vim.lsp.buf.add_workspace_folder()<CR>')
	--u.nnoremap_buf(bufnr, '<space>wr', '<cmd>lua vim.lsp.buf.remove_workspace_folder()<CR>')
	--u.nnoremap_buf(bufnr, '<space>wl', '<cmd>lua print(vim.inspect(vim.lsp.buf.list_workspace_folders()))<CR>')
end


-- git
function M.git_keymaps()
  return {
    noremap = true,
--     ['n ]c'] = { expr = true, "&diff ? ']c' : '<cmd>lua require\"gitsigns.actions\".next_hunk()<CR>'"},
--     ['n [c'] = { expr = true, "&diff ? '[c' : '<cmd>lua require\"gitsigns.actions\".prev_hunk()<CR>'"},
--     ['n <leader>hs'] = '<cmd>lua require"gitsigns".stage_hunk()<CR>',
--     ['v <leader>hs'] = '<cmd>lua require"gitsigns".stage_hunk({vim.fn.line("."), vim.fn.line("v")})<CR>',
--     ['n <leader>hu'] = '<cmd>lua require"gitsigns".undo_stage_hunk()<CR>',
--     ['n <leader>hr'] = '<cmd>lua require"gitsigns".reset_hunk()<CR>',
--     ['v <leader>hr'] = '<cmd>lua require"gitsigns".reset_hunk({vim.fn.line("."), vim.fn.line("v")})<CR>',
--     ['n <leader>hR'] = '<cmd>lua require"gitsigns".reset_buffer()<CR>',
--     ['n <leader>hp'] = '<cmd>lua require"gitsigns".prview_hunk()<CR>',
--     ['n <leader>hb'] = '<cmd>lua require"gitsigns".blame_line(true)<CR>',
    ['n <c-x>gb'] = '<cmd>lua require"gitsigns".blame_line(true)<CR>',
--     ['n <leader>hS'] = '<cmd>lua require"gitsigns".stage_buffer()<CR>',
--     ['n <leader>hU'] = '<cmd>lua require"gitsigns".reset_buffer_index()<CR>',
--     -- Text objects
--     ['o ih'] = ':<C-U>lua require"gitsigns.actions".select_hunk()<CR>',
--     ['x ih'] = ':<C-U>lua require"gitsigns.actions".select_hunk()<CR>'
  }
end

return M
